home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / MATH / EJCPLX01 / COMPLEX.PAS next >
Pascal/Delphi Source File  |  1989-07-21  |  25KB  |  865 lines

  1. { Complex Number Turbo 5.5 Package.                        }
  2. { Written by Eric Robert Jablow                            }
  3. { Version 0.1.  Completed July 20, 1989, 9:45 AM EDT.      }
  4. {            34 Hart Street                                }
  5. {            Port Jefferson Station, NY 11776              }
  6. {            (516)-331-6687 (until August 1.)              }
  7. {            ERIC JABLOW on EXEC-PC, Sound of Music.       }
  8. {            ejablow@dasys1.UUCP                           }
  9. {            eric%sbmath@sbee.sunysb.edu (USENET addresses)}
  10.  
  11. { TP 5.5 Copyright (c) 1989 by Borland International, Inc. }
  12. { Also uses Turbo Professional 5.0 copyright 1987, 1988,   }
  13. { 1989 by TurboPower Software.                             }
  14.  
  15. unit Complex;
  16.  
  17. {***************************************************}
  18. {*                                                 *}
  19. {* Turbo Pascal 5.5 object-oriented example.       *}
  20. {* This unit defines the complex numbers and       *}
  21. {* various operations on them.  Other units will   *}
  22. {* extend this to the Riemann sphere, quaternions, *}
  23. {* and so on.  More units will later be provided   *}
  24. {* to handle various classes of complex functions, *}
  25. {* the Mobius transformations, for example.  I     *}
  26. {* hope to write a curve and integration unit, at  *}
  27. {* least for the holomorphic functions.            *}
  28. {*                                                 *}
  29. {***************************************************}
  30.  
  31. {***************************************************}
  32. {*                                                 *}
  33. {* Copyright (c) 1989 by Eric Jablow.  You may use *}
  34. {* this unit freely in any non-profit application, *}
  35. {* as long as you provide credit to me.  Feel free *}
  36. {* to modify this unit too; just don't remove the  *}
  37. {* copyright notice.                               *}
  38. {*                                                 *}
  39. {***************************************************}
  40.  
  41. {$R+}
  42. {$S-}
  43.  
  44. interface
  45.  
  46. uses Objects,   {From TP5.5 by Borland International.}
  47.      Trig,      {An auxiliary unit for hyperbolic functions }
  48.                 {from the Turbo Professional Bonus Disk.    }
  49.                 {It is public-domain.                       }
  50.      TPDos,     {An extension to the Dos unit from TPro 5.0.}
  51.                 {The only use of this is OpenStdDev and     }
  52.                 {StdErrHandle in the ReportError method.    }
  53.      TPString;  {Also from TPro 5.0.  Its only use is HexPtr}
  54.                 {in the ReportError method.                 }
  55.  
  56. type
  57.  
  58.   MathString       = String[79];     {Enough to fit on one line.}
  59.  
  60. {****************************************************}
  61. {*                                                  *}
  62. {* The different error types this unit will handle. *}
  63. {*                                                  *}
  64. {****************************************************}
  65.  
  66.   ComplexError     = ( NoError,       { This insures that the true }
  67.                                       { errors have Ordinal Value  }
  68.                                       { greater than zero.         }
  69.  
  70.                        DivByZero,     { Dividing a non-zero number }
  71.                                       { by zero.  Use the Extended }
  72.                                       { Complex Numbers instead.   }
  73.  
  74.                        ZeroOverZero,  { Dividing zero by zero, or  }
  75.                                       { multiplying zero by an     }
  76.                                       { infinite extended complex  }
  77.                                       { number.                    }
  78.  
  79.                        BrArgRangeErr, { Silly value for the branch }
  80.                                       { angle in method BrArgument.}
  81.  
  82.                        LogError,      { Taking logarithm of 0.0,   }
  83.                                       { or any other logarithmic   }
  84.                                       { singularity.               }
  85.  
  86.                        InputError);   { EOF or a badly-formatted   }
  87.                                       { in the ReadNum method.     }
  88.  
  89. {******************************************************}
  90. {*                                                    *}
  91. {* The ComplexNumber object, and its various methods. *}
  92. {*                                                    *}
  93. {******************************************************}
  94.  
  95.   ComplexNumberPtr = ^ComplexNumber;
  96.  
  97.   ComplexNumber    = object(Base)     {Base is from the  OBJECTS unit}
  98.  
  99. {*********************************************************}
  100. {*                                                       *}
  101. {* Class variable definitions: real and imaginary parts. *}
  102. {*                                                       *}
  103. {*********************************************************}
  104.  
  105.     RealPart       : real;            { If z = x + iy, this is x, }
  106.     ImagPart       : real;            {            and this is y. }
  107.  
  108. {*********************************************************}
  109. {*                                                       *}
  110. {*      Ordinary constructors and destructors.           *}
  111. {*                                                       *}
  112. {*********************************************************}
  113.  
  114. { Create a complex number from two real numbers. }
  115.  
  116.     constructor Init(re : Real; im : Real);
  117.  
  118. { Convert a real number to a complex number. }
  119.  
  120.     constructor RealInit(re : Real);
  121.  
  122. { Copy a complex number to another. }
  123.  
  124.     constructor Copy(var w : ComplexNumber);
  125.  
  126. { Read a complex number from Input. }
  127.  
  128.     constructor ReadNum;
  129.  
  130. { Destroy a complex number. }
  131.  
  132.     destructor  Done; virtual;
  133.  
  134.  
  135. {********************************************}
  136. {*                                          *}
  137. {* Stream-oriented methods for reading and  *}
  138. {* writing complex numbers in binary form.  *}
  139. {* Streams are defined in the Objects unit. *}
  140. {*                                          *}
  141. {********************************************}
  142.  
  143.  
  144. { Read a complex number from a stream. }
  145.  
  146.     constructor Load(var S : Stream);
  147.  
  148. { Write a complex number to a stream.  }
  149.  
  150.     procedure   Store(var S : Stream);
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157. {***********************************}
  158. {*                                 *}
  159. {* Access the object's components. *}
  160. {*                                 *}
  161. {***********************************}
  162.  
  163. { Get Re z. }
  164.  
  165.     function    GetRealPart: real;
  166.  
  167. { Get Im z. }
  168.  
  169.     function    GetImagPart: real;
  170.  
  171. { Set Re z. }
  172.  
  173.     procedure   SetRealPart(x : Real);
  174.  
  175. { Set Im z. }
  176.  
  177.     procedure   SetImagPart(y: Real);
  178.  
  179. { Reset z. }
  180.  
  181.     procedure   CSet(x : Real; y : Real);
  182.  
  183.  
  184. {*******************************************}
  185. {*                                         *}
  186. {* Handle errors in the various routines.  *}
  187. {*                                         *}
  188. {*******************************************}
  189.  
  190.     procedure   ReportError( ErrorType : ComplexError);
  191.  
  192. {********************************************************}
  193. {*                                                      *}
  194. {* Equality tests.  EqualTo checks for exact equality,  *}
  195. {* and Approx checks for additive approximate equality. *}
  196. {* Similarly, MultApprox checks for multiplicatively    *}
  197. {* approximate equality.  The tolerance is epsilon.     *}
  198. {*                                                      *}
  199. {********************************************************}
  200.  
  201. { Exact equality--rare for real numbers on a computer. }
  202.  
  203.     function   EqualTo(  var w  : ComplexNumber) : Boolean;
  204.  
  205. { Additive approximate equality: Approx will be true   }
  206. { when both |Re z - Re w| and |Im z - Im w| < epsilon. }
  207.  
  208.     function   Approx(   var w  : ComplexNumber;
  209.                          epsilon:  real) : Boolean;
  210.  
  211. { Multiplicative approximate equality.  MultApprox     }
  212. { will be true when |Re z - Re w| <= epsilon*|Re z|    }
  213. {               and |Im z - Im w| <= epsilon*|Im z|    }
  214.  
  215.     function   MultApprox(var w : ComplexNumber;
  216.                          epsilon:  real) : Boolean;
  217.  
  218.  
  219. {****************************************************************}
  220. {*                                                              *}
  221. {*                   COMPLEX ARITHMETIC                         *}
  222. {*                                                              *}
  223. {* The four basic arithmetic functions: all done essentially as *}
  224. {* z --> z op w.  These all modify the base object.             *}
  225. {* ScalarMult is virtual because it extends to extended complex *}
  226. {* numbers and quaternions as multiplications by reals too.     *}
  227. {* Since the procedure in SubFrom works for any group, make it  *}
  228. {* virtual too.  Essentially, make addition and multiplication  *}
  229. {* static, and everything depending on them virtual.            *}
  230. {*                                                              *}
  231. {*  AbsValue and Conjugate are inserted here so as to define    *}
  232. {* Reciprocal, which is necessary to define DivideBy, even they *}
  233. {* are all important in their own right.  (If only one could    *}
  234. {* overload the ordinary arithmetic operations like +, -, etc.  *}
  235. {* as in C++.)   Conjugate is declared as virtual because it    *}
  236. {* can be extended to generalizations quite easily; after all,  *}
  237. {* it has no argument list.  The same goes for Reciprocal.      *}
  238. {* Finally, DivideBy is virtual because of the way it is        *}
  239. {* implemented.  The method given in DivideBy extends to any    *}
  240. {* integral domain.                                             *}
  241. {*                                                              *}
  242. {****************************************************************}
  243.  
  244.     procedure   AddTo(  var  w: ComplexNumber);           {z --> z + w.}
  245.  
  246.     procedure   Minus;                                    {z -->  - z. }
  247.  
  248.     procedure   SubFrom( var w: ComplexNumber); virtual;  {z --> z - w.}
  249.  
  250.     procedure   ScalarMult( t: real); virtual;            {z --> t * z.}
  251.  
  252.     procedure   MultBy( var w: ComplexNumber);            {z --> z * w.}
  253.  
  254.     procedure   Square;                                   {z --> z ^ 2.}
  255.  
  256.     function    AbsValue: real;                  {(x ^ 2 + y ^ 2) ^ 0.5}
  257.  
  258.     procedure   Conjugate; virtual;                       {z --> x - iy}
  259.  
  260.     procedure   Reciprocal; virtual;                      {z --> 1 / z.}
  261.  
  262.     procedure   DivideBy( var w: ComplexNumber); virtual; {z --> z / w.}
  263.  
  264. {* The argument of a (non-zero) complex number z is the angle   *}
  265. {* from the positive x-axis to the vector from the origin to z. *}
  266. {* BrArgument is provided for those situations where you cannot *}
  267. {* use the ordinary principal part of the arctan function.  See *}
  268. {* any good complex analysis book for details.  This happens    *}
  269. {* quite often with roots and logarithms.                       *}
  270.  
  271.  
  272.  
  273.     function    Argument: real;
  274.  
  275.     function    BrArgument( branchangle: real): real;
  276.  
  277.  
  278. { Various complex functions. }
  279.  
  280.     procedure  ComplexLog;                                {z -->log z.}
  281.  
  282.     procedure  BrComplexLog( branchangle : Real);
  283.  
  284.     procedure  ComplexExp;                                {z-->exp z.}
  285.  
  286.     procedure  ComplexSqrt;
  287.  
  288.     procedure  ComplexPower(        var w : ComplexNumber);
  289.  
  290.     procedure  RealPower(               t : Real);
  291.  
  292.     procedure  BrComplexPower(      var w : ComplexNumber;
  293.                               branchangle : Real);
  294.  
  295.     procedure  BrRealPower(t, branchangle : Real);
  296.  
  297.     procedure  ComplexIntPower( i : Integer);
  298.  
  299.     procedure  ComplexSin;
  300.  
  301.     procedure  ComplexCos;
  302.  
  303.     procedure  ComplexTan;
  304.  
  305.     procedure  ComplexSec;
  306.  
  307.     procedure  ComplexCsc;
  308.  
  309.     procedure  ComplexCot;
  310.  
  311. {***************************************************************}
  312. {*                                                             *}
  313. {*               INPUT AND OUTPUT                              *}
  314. {*                                                             *}
  315. {* Convert a complex number to a string so that you can put it *}
  316. {* into a Write or WriteLn statement.  Since no parameter list *}
  317. {* is necessary, it should obviously be virtual.               *}
  318. {*                                                             *}
  319. {***************************************************************}
  320.  
  321.     function    ToString: MathString; virtual;
  322.     function    ToFormatted( width, dwidth: Byte;
  323.                                exponential: Boolean): MathString; virtual;
  324.     procedure   Display; virtual;
  325.     procedure   FormattedDisplay( width, dwidth: Byte;
  326.                                     exponential: Boolean); virtual;
  327.  
  328.  
  329.   end;
  330.  
  331. const
  332.  
  333. { 0. }
  334.   CZero            : ComplexNumber = (Realpart : 0.0; ImagPart : 0.0);
  335.  
  336. { 1. }
  337.   COne             : ComplexNumber = (Realpart : 1.0; ImagPart : 0.0);
  338.  
  339. { i  }
  340.   CI               : ComplexNumber = (Realpart : 0.0; ImagPart : 1.0);
  341.  
  342.  
  343. implementation
  344.  
  345. function Floor( x: real) : LongInt;
  346. var
  347.   l: LongInt;
  348. begin
  349.   If x >= 0.0 then
  350.     l := Trunc(x)
  351.   else                 { x is negative. }
  352.     begin
  353.     x := -x;           { Take the absolute value of x.}
  354.     l := Trunc(x);
  355.     If x > l then      { x was originally not a negative integer.}
  356.       l := l + 1;      {      We must round _away_ from zero.    }
  357.  
  358.     l := -l            {Now, convert back to a negative integer. }
  359.     end;
  360.   Floor := l
  361. end;  { Floor }
  362.  
  363. {*******************************************************************}
  364.  
  365. constructor ComplexNumber.Init( re: real; im: real);
  366. begin
  367.   Realpart := re;
  368.   ImagPart := im
  369. end;  { Init }
  370.  
  371. constructor ComplexNumber.RealInit( re: real);
  372. begin
  373.   Realpart := re;
  374.   ImagPart := 0.0
  375. end;  { RealInit }
  376.  
  377. constructor ComplexNumber.Copy( var w: ComplexNumber);
  378. begin
  379.   Self := w
  380. end;  { Copy }
  381.  
  382. { This Routine needs a lot of work.  It takes input exactly }
  383. { the way the output routines write them.                   }
  384.  
  385. constructor ComplexNumber.ReadNum;
  386. var
  387.   imag : Char;
  388. begin
  389.   {$I-}
  390.   Read(RealPart);
  391.   {$I+}
  392.   if IOResult <> 0 then ReportError(InputError);
  393.   if Eof OR EoLn then
  394.     ImagPart := 0.0
  395.   else begin
  396.     {$I-}
  397.     Read(ImagPart, imag);
  398.     {$I+}
  399.     if (IOResult <>0) OR (imag <> 'i') then ReportError(InputError);
  400.   end
  401. end; { ReadNum }
  402.  
  403. destructor ComplexNumber.Done;
  404. begin
  405. end;  { Done }
  406.  
  407.  
  408. {*******************************************************************}
  409.  
  410.  
  411. constructor ComplexNumber.Load(var S : Stream);
  412. begin
  413.   S.Read(RealPart, SizeOf(Real));
  414.   if S.Status <> 0 then Fail;
  415.   S.Read(ImagPart, SizeOf(Real));
  416.   if S.Status <> 0 then Fail;
  417. end; { Load }
  418.  
  419. procedure ComplexNumber.Store(var S : Stream);
  420. begin
  421.   S.Write(RealPart, SizeOf(Real));
  422.   S.Write(ImagPart, SizeOf(Real))
  423. end; { Store }
  424.  
  425.  
  426. {*******************************************************************}
  427.  
  428. function   ComplexNumber.GetRealPart;
  429. begin
  430.   GetRealPart := RealPart
  431. end;  { GetRealPart }
  432.  
  433. function   ComplexNumber.GetImagPart;
  434. begin
  435.   GetImagPart := ImagPart
  436. end;  { GetImagPart }
  437.  
  438.  
  439. procedure  ComplexNumber.SetRealPart(x : Real);
  440. begin
  441.   RealPart := x
  442. end;  { SetRealPart }
  443.  
  444. procedure  ComplexNumber.SetImagPart(y : Real);
  445. begin
  446.   ImagPart := y
  447. end;  { GetImagPart }
  448.  
  449. procedure  ComplexNumber.CSet(x : Real; y : Real);
  450. begin
  451.   RealPart := x;
  452.   ImagPart := y
  453. end;  { CSet }
  454.  
  455. {*******************************************************************}
  456.  
  457.  
  458. { OpenStdDev is from the Turbo Professional 5.5 TPDos unit. }
  459. { HexPtr is from its TPString unit.                         }
  460.  
  461. procedure   ComplexNumber.ReportError( errortype : ComplexError);
  462. const
  463.   Message : ARRAY[ComplexError] OF MathString =
  464.     ( 'No Error.',
  465.       'You tried to divide a non-zero number by zero.',
  466.       'You tried to divide zero by zero.',
  467.       'The branchangle you sent to BrArgument was too large in magnitude.',
  468.       'You tried to take the logarithm of 0.0 +0.0*i.',
  469.       'EOF or malformed input on read.');
  470.  
  471.   TProError = 255;
  472.  
  473. var
  474.   StdErr  : Text;
  475.  
  476. begin
  477.   if NOT OpenStdDev( StdErr, StdErrHandle) then
  478.     Halt(TProError);
  479.   Writeln( StdErr, '***Error in ComplexNumber Unit ***');
  480.   Writeln( Stderr, Message[errortype] );
  481.   Write(   StdErr, 'The ComplexNumber object was at ');
  482.   Writeln( StdErr, HexPtr(@Self) + '.');
  483.   Close(   StdErr);
  484.   Halt( Ord(errortype) )
  485. end;
  486.  
  487. {*******************************************************************}
  488.  
  489.  
  490. function  ComplexNumber.EqualTo( var w: ComplexNumber): Boolean;
  491. begin
  492.   EqualTo :=     (RealPart = w.RealPart)
  493.              AND (ImagPart = w.ImagPart)
  494. end;
  495.  
  496. function  ComplexNumber.Approx(  var w : ComplexNumber;
  497.                                epsilon : real): Boolean;
  498. begin
  499.   Approx :=     (Abs(RealPart - w.RealPart) < epsilon)
  500.             AND (Abs(ImagPart - w.ImagPart) < epsilon)
  501. end;
  502.  
  503. function  ComplexNumber.MultApprox( var  w : ComplexNumber;
  504.                                    epsilon : real): Boolean;
  505. begin
  506.   MultApprox :=  (Abs(RealPart - w.RealPart) <= epsilon * Abs(RealPart))
  507.              AND (Abs(ImagPart - w.ImagPart) <= epsilon * Abs(ImagPart))
  508. end;
  509.  
  510.  
  511. {*******************************************************************}
  512.  
  513.  
  514. procedure  ComplexNumber.Addto( var w: ComplexNumber);
  515. begin
  516.   RealPart := RealPart + w.GetRealPart;
  517.   ImagPart := ImagPart + w.GetImagPart
  518. end;
  519.  
  520. procedure  ComplexNumber.Minus;
  521. begin
  522.   RealPart := -RealPart;
  523.   ImagPart := -ImagPart
  524. end;
  525.  
  526. procedure  ComplexNumber.SubFrom( var w: ComplexNumber);
  527. begin
  528.   Minus;     {     z --> -z.    }
  529.   AddTo(w);  { now z --> w - z. }
  530.   Minus      { now z --> z - w. }
  531. end;
  532.  
  533. procedure  ComplexNumber.ScalarMult( t: real);
  534. begin
  535.   RealPart := RealPart * t;
  536.   ImagPart := ImagPart * t
  537. end;
  538.  
  539. procedure  ComplexNumber.MultBy( var w: ComplexNumber);
  540.  
  541. var
  542.   temp1, temp2, temp3: Real;
  543.  
  544. begin
  545.   temp1 := (RealPart + w.RealPart) * (ImagPart + w.ImagPart);
  546.   temp2 := RealPart * w.RealPart;
  547.   temp3 := ImagPart * w.ImagPart;
  548.   RealPart := temp2 - temp3;
  549.   ImagPart := temp1 - (temp2 + temp3)
  550. end;
  551.  
  552. procedure ComplexNumber.Square;
  553. var
  554.   tempreal, tempimag: Real;
  555. begin
  556.   tempreal := Sqr(RealPart) - Sqr(ImagPart);
  557.   tempimag := RealPart * ImagPart;
  558.   RealPart := tempreal;
  559.   ImagPart := tempimag + tempimag { Faster than multiplying}
  560.                                   { by 2.                  }
  561. end;
  562.  
  563. function  ComplexNumber.AbsValue: real;
  564. begin
  565.   AbsValue := Sqrt( Sqr(RealPart) + Sqr(ImagPart))  {TP5.5 is probably faster.}
  566. end;
  567.  
  568.  
  569. procedure  ComplexNumber.Conjugate;
  570. begin
  571.   ImagPart := - ImagPart
  572. end;
  573.  
  574. procedure  ComplexNumber.Reciprocal;
  575. var
  576.   temp: real;
  577.  
  578. begin
  579.  
  580.   if EqualTo(CZero) then
  581.     ReportError(DivByZero);
  582.  
  583.   Conjugate;
  584.   temp := 1/ (Sqr(RealPart) + Sqr(ImagPart));
  585.   ScalarMult(temp)
  586. end;
  587.  
  588. procedure  ComplexNumber.DivideBy( var w: ComplexNumber);
  589. var
  590.   winverse: ComplexNumber;  { 1 / w, eventually.}
  591.  
  592. begin
  593.  
  594.   if EqualTo(CZero) AND w.EqualTo(CZero) then
  595.       ReportError(ZeroOverZero);
  596.  
  597.   winverse.Copy(w);         { Set  winverse = w.    }
  598.   winverse.Reciprocal;      { Now, winverse = 1 / w.}
  599.   MultBy(winverse)          { z --> z * (1 / w).    }
  600. end;
  601.  
  602. {*******************************************************************}
  603.  
  604.  
  605. function  ComplexNumber.Argument: real;
  606. { Give the argument of the complex number, in the interval [-pi, pi) }
  607. { If the number is 0, report 0 back.}
  608.  
  609. var
  610.   theta: real;
  611.  
  612. begin
  613.   if RealPart = 0.0 then
  614.     begin
  615.     if ImagPart = 0.0 then
  616.       theta := 0.0
  617.       else
  618.     if ImagPart > 0.0 then
  619.       theta := PI/2.0
  620.       else
  621.       theta := -PI/2.0
  622.     end
  623.   else theta := ArcTan( ImagPart/ RealPart);
  624.  
  625.   if (RealPart < 0) then begin
  626.     if (ImagPart >= 0) then
  627.       theta := theta + pi
  628.     else
  629.       theta := theta - pi
  630.     end;
  631.  
  632.   Argument := theta
  633. end;
  634.  
  635. function  ComplexNumber.BrArgument( branchangle: real): real;
  636. const
  637.   maxbranchangle = 2.0 * 3.14159 * (MAXLONGINT - 1);
  638. var
  639.   principal: real;
  640.   adjust:    longint;
  641. begin
  642.   if (Abs(branchangle) > Maxbranchangle) then ReportError(BrArgRangeErr);
  643.  
  644.   principal := Argument;
  645.   adjust := Floor( (principal - branchangle)/ (2.0 * PI));
  646.   BrArgument := principal - 2.0 * PI * adjust
  647. end;
  648.  
  649. procedure  ComplexNumber.ComplexLog;
  650. var
  651.   modulus : Real;
  652. begin
  653.   modulus := AbsValue;
  654.   if ( modulus = 0.0 ) then
  655.     ReportError(LogError);  {Doesn't return.}
  656.   ImagPart := Argument;
  657.   RealPart := Ln(modulus)
  658. end;
  659.  
  660. procedure  ComplexNumber.BrComplexLog( branchangle : Real);
  661. var
  662.   modulus : Real;
  663. begin
  664.   modulus := AbsValue;
  665.   if ( modulus = 0.0 ) then
  666.     ReportError(LogError);  {Doesn't return.}
  667.   ImagPart := BrArgument( branchangle);
  668.   RealPart := Ln(modulus)
  669. end;
  670.  
  671. procedure  ComplexNumber.ComplexExp;
  672. var
  673.   temp : Real;
  674. begin
  675.   temp := Exp(RealPart);
  676.   RealPart := temp * Cos(ImagPart);
  677.   ImagPart := temp * Sin(ImagPart)
  678. end;
  679.  
  680.  
  681. procedure  ComplexNumber.ComplexSqrt;
  682. var
  683.   newModulus  : Real;
  684.   newArgument : Real;
  685. begin
  686.   newModulus  := Sqrt(AbsValue);
  687.   newArgument := Argument/2.0;
  688.   RealPart    := newModulus * Cos(newArgument);
  689.   ImagPart    := newModulus * Sin(NewArgument);
  690. end;
  691.  
  692. procedure  ComplexNumber.ComplexPower( var w : ComplexNumber);
  693. begin
  694.   ComplexLog;
  695.   MultBy(w);
  696.   ComplexExp
  697. end;
  698.  
  699. procedure  ComplexNumber.RealPower( t : Real);
  700. begin
  701.   ComplexLog;
  702.   ScalarMult(t);
  703.   ComplexExp
  704. end;
  705.  
  706. procedure  ComplexNumber.BrComplexPower( var w : ComplexNumber;
  707.                                    branchangle : Real);
  708. begin
  709.   BrComplexLog( branchangle);
  710.   MultBy(w);
  711.   ComplexExp
  712. end;
  713.  
  714. procedure  ComplexNumber.BrRealPower( t, branchangle : Real);
  715. begin
  716.   BrComplexLog( branchangle);
  717.   ScalarMult(t);
  718.   ComplexExp
  719. end;
  720.  
  721.  
  722. procedure  ComplexNumber.ComplexIntPower{ i : Integer};
  723. const
  724.   limit = 12; { This is a tweakable parameter; since ComplexLog is slow, }
  725.               { if |i| <= limit we will do this by multiplication. Else, }
  726.               { we use ComplexLog and ComplexExp.  I chose 12 because it }
  727.               { largest integer such that this function requires at most }
  728.               { six multiplications.                                     }
  729. var
  730.   w        : ComplexNumber;
  731.   negative : Boolean;
  732. begin
  733.   if ( Abs(i) > limit ) then
  734.     begin
  735.       w.RealInit(i);
  736.       ComplexPower(w)
  737.     end
  738.   else
  739.     if i = 0 then Self := COne
  740.   else begin
  741.     negative := i < 0;
  742.     i := Abs(i);
  743.     while i > 1 do begin          { Suppose i = 2*m + k, k = 0 or 1.}
  744.       w.Copy(Self);               { w --> z }
  745.       Square;                     { z --> z^2}
  746.       ComplexIntPower(i div 2);   { z --> z^(2*n)}
  747.       if Odd(i) then MultBy(w); { z --> z^(2*n+k)}
  748.     end; {while}
  749.     if negative then Reciprocal
  750.     end
  751. end;   {ComplexIntPower}
  752.  
  753.  
  754. {*******************************************************************}
  755.  
  756.  
  757. procedure  ComplexNumber.ComplexSin;
  758. var
  759.   temp: Real;
  760. begin
  761.   temp     := Sin(RealPart) * Cosh(ImagPart);
  762.   ImagPart := Cos(RealPart) * Sinh(ImagPart);
  763.   RealPart := temp
  764. end;
  765.  
  766. procedure  ComplexNumber.ComplexCos;
  767. var
  768.   temp : Real;
  769. begin
  770.   temp     :=   Cos(RealPart) * Cosh(ImagPart);
  771.   ImagPart := - Sin(RealPart) * Sinh(ImagPart);
  772.   RealPart :=   temp
  773. end;
  774. procedure  ComplexNumber.ComplexTan;
  775. var
  776.   w : ComplexNumber;
  777. begin
  778.   w.Copy(Self);
  779.   ComplexSin;
  780.   w.ComplexCos;
  781.   DivideBy(w)
  782. end;
  783.  
  784. procedure  ComplexNumber.ComplexSec;
  785. begin
  786.   ComplexCos;
  787.   Reciprocal
  788. end;
  789.  
  790. procedure  ComplexNumber.ComplexCsc;
  791. begin
  792.   ComplexSin;
  793.   Reciprocal
  794. end;
  795.  
  796. procedure  ComplexNumber.ComplexCot;
  797. var
  798.   w : ComplexNumber;
  799. begin
  800.   w.Copy(Self);
  801.   ComplexCos;
  802.   w.ComplexSin;
  803.   DivideBy(w)
  804. end;
  805.  
  806. {*******************************************************************}
  807.  
  808. function  ComplexNumber.ToString: MathString;
  809. var
  810.   ImSign:   String[2];
  811.   ReString: MathString;
  812.   ImString: MathString;
  813.  
  814. begin
  815.   if ImagPart < 0 then
  816.     ImSign := ' -'
  817.   else
  818.     ImSign := ' +';
  819.  
  820.   Str( RealPart, ReString);
  821.   Str( Abs(ImagPart), ImString);
  822.   ToString := ReString + ImSign + ImString + '*i'
  823. end;
  824.  
  825. function  ComplexNumber.ToFormatted(width, dwidth: Byte;
  826.                                       exponential: Boolean): MathString;
  827. var
  828.   ImSign: String[2];
  829.   ReString: MathString;
  830.   ImString: MathString;
  831.  
  832. begin
  833.   if ( ImagPart < 0 ) then
  834.     ImSign := ' -'
  835.   else
  836.     ImSign := ' +';
  837.  
  838.   if ( exponential ) then
  839.     begin
  840.       Str( RealPart : width, ReString);
  841.       Str( Abs(ImagPart) : width, ImString)
  842.     end
  843.   else
  844.     begin
  845.       Str( RealPart : width : dwidth, ReString);
  846.       Str( Abs(ImagPart) : width : dwidth, ImString)
  847.     end;
  848.   ToFormatted := ReString + ImSign + ImString + 'i'
  849. end;
  850.  
  851. procedure ComplexNumber.Display;
  852. begin
  853.   Write( ToString )
  854. end;
  855.  
  856. procedure ComplexNumber.FormattedDisplay( width, dwidth: Byte;
  857.                                             exponential: Boolean);
  858. begin
  859.   Write( ToFormatted( width, dwidth, exponential))
  860. end;
  861.  
  862.  
  863. end.
  864.  
  865.